using System;
using System.Diagnostics;

using Evaluant.Uss;
using Evaluant.Uss.Common;
using Evaluant.Uss.Commands;

namespace Evaluant.Uss.Sync
{
	/// <summary>
	/// Visitor pattern to execute concrete commands
	/// </summary>
	class SyncCommandProcessor : ICommandProcessor
	{
        private int order = 0;
        private Transaction transaction;
        private int transactionId = 0;

        public SyncCommandProcessor(Transaction transaction, int transactionId)
        {
            this.transaction = transaction;
            this.transactionId = transactionId;
        }

		public void Process(Command c)
		{
		}

        DateTime previous = DateTime.MinValue;

        private void PopulateDefaults(Entity e, Command c)
        {
            e.SetValue(SyncUtils.CLIENTID, c.ClientId);
            e.SetValue(SyncUtils.PROCESSED, DateTime.Now);
            e.SetValue(SyncUtils.NUMBER, order++);
            e.SetValue(SyncUtils.TRANSACTION, transactionId);
        }

		public void Process(CreateEntityCommand c)
		{
            Entity e = new Entity(SyncUtils.CREATE_ENTITY);
            
            PopulateDefaults(e, c);

            e.SetValue(SyncUtils.PARENTID, c.ParentId);
            e.SetValue(SyncUtils.TYPE, c.Type);
            
            transaction.Serialize(e);
		}

		public void Process(DeleteEntityCommand c)
		{
            Entity e = new Entity(SyncUtils.DELETE_ENTITY);
            PopulateDefaults(e, c);

            e.SetValue(SyncUtils.PARENTID, c.ParentId);
            e.SetValue(SyncUtils.TYPE, c.Type);

            transaction.Serialize(e);
        }

		public void Process(CreateAttributeCommand c)
		{
            Entity e = new Entity(SyncUtils.CREATE_ATTRIBUTE);
            PopulateDefaults(e, c);

            e.SetValue(SyncUtils.PARENTID, c.ParentId);
            e.SetValue(SyncUtils.PARENTTYPE, c.ParentType);
            e.SetValue(SyncUtils.TYPE, c.Type.Name);
            e.SetValue(SyncUtils.NAME, c.Name);
            e.SetValue(SyncUtils.VALUE, Utils.SerializeToString(c.Value));

            transaction.Serialize(e);
        }

		public void Process(CompoundCreateCommand c)
		{
			Process((CreateEntityCommand)c);
			foreach(CreateAttributeCommand cc in c.InnerCommands)
				Process(cc);
		}

		public void Process(CompoundUpdateCommand c)
		{
			foreach(Command cc in c.InnerCommands)
				cc.Accept(this);
		}

		public void Process(UpdateAttributeCommand c)
		{
            Entity e = new Entity(SyncUtils.UPDATE_ATTRIBUTE);
            PopulateDefaults(e, c);

            e.SetValue(SyncUtils.PARENTID, c.ParentId);
            e.SetValue(SyncUtils.PARENTTYPE, c.ParentType);
            e.SetValue(SyncUtils.TYPE, c.Type.Name);
            e.SetValue(SyncUtils.NAME, c.Name);
            e.SetValue(SyncUtils.VALUE, Utils.SerializeToString(c.Value));

            transaction.Serialize(e);
        }

		public void Process(DeleteAttributeCommand c)
		{
            Entity e = new Entity(SyncUtils.DELETE_ATTRIBUTE);
            PopulateDefaults(e, c);

            e.SetValue(SyncUtils.PARENTID, c.ParentId);
            e.SetValue(SyncUtils.PARENTTYPE, c.ParentType);
            e.SetValue(SyncUtils.NAME, c.Name);
            e.SetValue(SyncUtils.TYPE, c.Type.Name);

            transaction.Serialize(e);
        }

		public void Process(CreateReferenceCommand c)
		{
            Entity e = new Entity(SyncUtils.CREATE_REFERENCE);
            PopulateDefaults(e, c);

            e.SetValue(SyncUtils.PARENTID, c.ParentId);
            e.SetValue(SyncUtils.PARENTTYPE, c.ParentType);
            e.SetValue(SyncUtils.ROLE, c.Role);
            e.SetValue(SyncUtils.CHILDID, c.ChildId);
            e.SetValue(SyncUtils.CHILDTYPE, c.ChildType);

            transaction.Serialize(e);
        }

		public void Process(DeleteReferenceCommand c)
		{
            Entity e = new Entity(SyncUtils.DELETE_REFERENCE);
            PopulateDefaults(e, c);

            e.SetValue(SyncUtils.PARENTID, c.ParentId);
            e.SetValue(SyncUtils.PARENTTYPE, c.ParentType);
            e.SetValue(SyncUtils.ROLE, c.Role);
            e.SetValue(SyncUtils.CHILDID, c.ChildId);
            e.SetValue(SyncUtils.CHILDTYPE, c.ChildType);

            transaction.Serialize(e);
        }

        private string _NewId;
        public string NewId
        {
            get { return _NewId; }
            set { _NewId = value; }
        }

	}
}
